package com.jfire.orm.function.impl;

import java.lang.reflect.Method;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Resource;
import javax.sql.DataSource;
import com.jfire.baseutil.PackageScan;
import com.jfire.orm.annotation.BatchUpdate;
import com.jfire.orm.annotation.Query;
import com.jfire.orm.annotation.Update;
import com.jfire.orm.function.SessionFactory;
import com.jfire.orm.function.SqlSession;
import com.jfire.orm.util.DaoFactory;
import com.jfire.orm.util.InterfaceMapperFactory;
import com.jfire.orm.util.MapBeanFactory;

@Resource
public class SessionFactoryImpl implements SessionFactory
{
    @Resource
    private DataSource              dataSource;
    private ThreadLocal<SqlSession> sessionLocal = new ThreadLocal<>();
    private String                  scanPackage;
    
    public SessionFactoryImpl()
    {
    
    }
    
    public SessionFactoryImpl(DataSource dataSource)
    {
        this.dataSource = dataSource;
    }
    
    public void init()
    {
        Set<String> set = new HashSet<>();
        String[] packageNames = scanPackage.split(";");
        for (String each : packageNames)
        {
            for (String each2 : PackageScan.scan(each))
            {
                set.add(each2);
            }
        }
        try
        {
            MapBeanFactory.build(set);
            DaoFactory.buildDaoBean(set);
            next:
            for (String each : set)
            {
                Class<?> ckass = Class.forName(each);
                if (ckass.isInterface())
                {
                    for (Method method : ckass.getMethods())
                    {
                        if (method.isAnnotationPresent(Query.class) || method.isAnnotationPresent(Update.class) || method.isAnnotationPresent(BatchUpdate.class))
                        {
                            InterfaceMapperFactory.buildMapper(ckass);
                            continue next;
                        }
                    }
                }
            }
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        
    }
    
    @Override
    public SqlSession getCurrentSession()
    {
        return sessionLocal.get();
    }
    
    @Override
    public SqlSession openSession()
    {
        try
        {
            SqlSession session = new SqlSessionImpl(dataSource.getConnection(), this);
            return session;
        }
        catch (SQLException e)
        {
            throw new RuntimeException(e);
        }
    }
    
    @Override
    public void removeCurrentSession()
    {
        sessionLocal.remove();
    }
    
    public void setDataSource(DataSource dataSource)
    {
        this.dataSource = dataSource;
    }
    
    @Override
    public void setCurrentSession(SqlSession session)
    {
        sessionLocal.set(session);
    }
    
    public void setScanPackage(String scanPackage)
    {
        this.scanPackage = scanPackage;
    }
    
}
